#include "StdAfx.h"
#include "User.h"
#include "Utilities.h"

#include <tchar.h>
#include <Sddl.h>

User::User(const TCHAR* user, const TCHAR* subKey)
    : m_controlled(FALSE)
{
    memset(m_KeyStr, 0, sizeof(m_KeyStr));

    static TCHAR currentUser[256] = {0};
    if (currentUser[0] == 0)
    {
        DWORD size = sizeof(currentUser)/sizeof(TCHAR);
        if (!GetUserName(currentUser, &size))
            currentUser[0] = 0;
    }
    m_isCurrent = 0 == _tcsicmp(user, currentUser);

    static TCHAR userPath[1000] = {0};
    if (userPath[0] == 0)
    {
        if (FAILED(SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, userPath)))
        {
            userPath[0] = 0;
            Log(_T("SHGetFolderPath in InitUser failed\n"));
        }
        TCHAR* pUser = _tcsrchr(userPath, _T('\\'));
        if (pUser != NULL)
        {
            *pUser = 0;
        }
    }

    _tcscpy_s(m_User, sizeof(m_User)/sizeof(TCHAR), user);
    if (userPath[0] != 0)
        _stprintf_s(m_Profile, sizeof(m_Profile)/sizeof(TCHAR), _T("%s\\%s\\NTUser.dat"), userPath, user);
    else
        m_Profile[0];

    if (FAILED(SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, m_Path)))
    {
        m_Path[0] = 0;
        Log(_T("SHGetFolderPath failed\n"));
    }

    if (m_isCurrent == FALSE)
    {
        _stprintf_s(m_KeyStr, sizeof(m_KeyStr)/sizeof(TCHAR), _T("%s\\%s"), user, subKey);
    }
    else
    {
        DWORD sidSize = 0;
        DWORD domSize = 0;
        SID_NAME_USE snu;
        LookupAccountName(NULL, m_User, NULL, &sidSize, NULL, &domSize, &snu);
        DWORD err = GetLastError();
        if (err == ERROR_INSUFFICIENT_BUFFER)
        {
            BYTE* pSid = new BYTE[sidSize];
            TCHAR* dom = new TCHAR[domSize];
            if (LookupAccountName(NULL, m_User, (PSID)pSid, &sidSize, dom, &domSize, &snu))
            {
                TCHAR* sidStr;
                if (ConvertSidToStringSid((PSID)pSid, &sidStr))
                {
                    _stprintf_s(m_KeyStr, sizeof(m_KeyStr)/sizeof(TCHAR), _T("%s\\%s"), sidStr, subKey);
                    LocalFree(sidStr);
                }
            }
            else
            {
                CString s;
                s.Format(_T("LookupAccountName failed (%d)\n"), GetLastError());
                Log(s);
            }
            delete[] dom;
            delete[] pSid;
        }
        else
        {
            CString s;
            s.Format(_T("LookupAccountName failed (%d)\n"), err);
            Log(s);
        }
    }
}


User::~User(void)
{
}


int User::ReadConfig(const BYTE* config)
{
    const BYTE* pConf = config;
    m_controlled = *pConf!=0;
    return m_timeTable.ReadConfig(pConf+1);
}


int User::SaveConfig(BYTE* config)
{
    BYTE* pConf = config;
    *pConf = m_controlled!=0;
    return (1+m_timeTable.SaveConfig(pConf+1));
}


UserStatus User::HasToStop(SYSTEMTIME& st)
{
    UserStatus b = m_timeTable.HasToStop(st);
    if (b == CanContinue)
        b = m_timeTable.HasToStop(Day(st), m_currentTimes);
    return b;
}
